/**
 * 20210818 created by jordia
 * 20220304:[require] to [import]...jordia
 * 20220927:rectify UV setting
 */
import {Object3D,TrianglesDrawMode,BufferGeometry,BufferAttribute,ShaderMaterial,AlwaysDepth} from 'three';

/**
 * 屏幕空间面片
 *     TOP
 *      |
 *      |
 *      |
 *   LEFT,BOTTOM--------------RIGHT
 *
 * 获取geometry、material编辑通用属性
 * @param  left {number} 左侧位置：0，大于1的数表示像素单位，否则为比例
 * @param  right {number} 右侧位置：1，大于1的数表示像素单位，否则为比例
 * @param  bottom {number} 底部位置：0，大于1的数表示像素单位，否则为比例
 * @param  top {number} 顶部位置：1，大于1的数表示像素单位，否则为比例
 * @param  width {number} 屏幕尺寸宽
 * @param  height {number} 屏幕尺寸高
 */
export default class FullScreenQuad extends Object3D{
    constructor(values={}){
        super();
        this._values=values;
        this.init();
    }

    //......................................public............................................

    get geometry(){
        return this._geometry;
    }

    get material(){
        return this._material;
    }

    set left(num){
        this._values.left=num;
        this.updatePositions();
    }
    get left(){
        return this._values.left;
    }

    set right(num){
        this._values.right=num;
        this.updatePositions();
    }
    get right(){
        return this._values.right;
    }

    set bottom(num){
        this._values.bottom=num;
        this.updatePositions();
    }
    get bottom(){
        return this._values.bottom;
    }

    set top(num){
        this._values.top=num;
        this.updatePositions();
    }
    get top(){
        return this._values.top;
    }

    /**
     * 设置面片尺寸
     * @param left {number} 左侧
     * @param right {number} 右侧
     * @param bottom {number} 底部
     * @param top {number} 顶部
     */
    setRect(left,right,bottom,top){
        this._values.left=left;
        this._values.right=right;
        this._values.bottom=bottom;
        this._values.top=top;
        this.updatePositions();
    }

    /**
     * 设置显示尺寸（像素，窗体尺寸改变时）
     * @param width
     * @param height
     */
    setSize(width,height){
        this._values.width=width;
        this._values.height=height;
        this.updatePositions();
    }

    //......................................private...........................................

    init(){
        this.initVariable();
        this.initComponents();
    }
    initVariable(){
        this.isMesh=true;
        this.drawMode=TrianglesDrawMode;
        this._geometry=null;
        this._material=null;
        this._values.left=this._values.left||0;
        this._values.right=this._values.right||1;
        this._values.top=this._values.top||1;
        this._values.bottom=this._values.bottom||0;
        this._values.width=this._values.width||window.innerWidth;
        this._values.height=this._values.height||window.innerHeight;
    }
    initComponents(){
        this.initGeometry();
        this.initMaterial();
    }

    /**
     * 属性改变时更新图形
     */
    updatePositions(){
        this.setPositions();
        this._geometry.getAttribute('position').copyArray(this._positions);
        this._geometry.getAttribute('position').needsUpdate=true;
    }

    /**
     * 转换尺寸（将像素转化为比例）
     * @param num
     * @param isX
     * @returns {number|*}
     */
    convertSize(num,isX){
        if(num<=1){
            return num;
        }else{
            return isX?num/this._values.width:num/this._values.height;
        }
    }

    /**
     * 设置顶点属性
     */
    setPositions(){
        let left=this.convertSize(this._values.left,true);
        let right=this.convertSize(this._values.right,true);
        let bottom=this.convertSize(this._values.bottom,false);
        let top=this.convertSize(this._values.top,false);
        this._positions[0]=left;
        this._positions[1]=bottom;
        this._positions[2]=0;

        this._positions[3]=right;
        this._positions[4]=bottom;
        this._positions[5]=0;

        this._positions[6]=right;
        this._positions[7]=top;
        this._positions[8]=0;

        this._positions[9]=left;
        this._positions[10]=top;
        this._positions[11]=0;
    }
    initGeometry(){
        this._geometry=new BufferGeometry();
        this._positions=new Float32Array(12);
        this.setPositions();
        this._uvs=new Float32Array([0,0,1,0,1,1,0,1]);
        this._geometry.setIndex([0,1,2,0,2,3]);
        this._geometry.setAttribute('position',new BufferAttribute(this._positions,3));
        this._geometry.setAttribute('uv',new BufferAttribute(this._uvs,2));
        this._geometry.setDrawRange(0,6);
    }
    initMaterial(){
        this._material=new ShaderMaterial();
        this.initUniforms();
        this.initVertexShader();
        this.initFragmentShader();
        this.initializeMaterial();
    }

    /**
     * 初始化材质uniforms
     */
    initUniforms(){
        this._material.uniforms={};
    }

    /**
     * 初始化顶点着色器
     */
    initVertexShader(){
        this._material.vertexShader=`
                varying vec2 vUv;
                void main(){
                    vUv=vec2(uv.xy);
                    vec3 pos=position.xyz;
                    gl_Position=vec4(pos.xy*2.-1.,0.,1.);
                }
            `;
    }

    /**
     * 初始化片元着色器
     */
    initFragmentShader() {
        this._material.fragmentShader = `
                varying vec2 vUv;
                void main(){
                    gl_FragColor=vec4(0.5,1.,0.,0.8);
                }
            `;
    }
    initializeMaterial() {
        this._material.transparent = true;
        this._material.depthWrite = false;
        this._material.depthFunc = AlwaysDepth;
    }

}